package com.example.demo.shiro.realm;

import com.example.demo.common.JwtUtils;
import com.example.demo.service.IUserService;
import com.example.demo.shiro.filter.JwtToken;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;

/**
 * @author zhaiding
 * @since 2019/5/11
 */
@Slf4j
public class CustomRealm extends AuthorizingRealm {

    @Resource
    private IUserService userService;

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }


    /**
     * 清空所有关联认证
     */
    public void clearAllCachedAuthorizationInfo() {
        Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
        if (cache != null) {
            cache.clear();
        }
    }

    /**
     * 清除指定用户的关联认证
     */
    public void clearCachedAuthorizationInfoByUserName(String username) {
        Cache<Object, AuthorizationInfo> cache = getAuthorizationCache();
        if (cache != null) {
            cache.remove(username);
        }
    }

    /**
     * 清除用户的关联认证
     */
    public void clearCachedAuthorizationInfo() {
        this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
    }

    /**
     * 授权
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        log.info("权限 -----------");

        String username = (String) principalCollection.getPrimaryPrincipal();
        // 判断用户名是否存在
        if (StringUtils.isEmpty(username)) {
            throw new RuntimeException("获取用户授权信息失败");
        }
        // todo 获取用户权限

        // 创建一个授权对象
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        authorizationInfo.addRole("admin");
        authorizationInfo.addStringPermission("user");
        return authorizationInfo;
    }

    /**
     * 认证
     *
     * @throws AuthenticationException 认证失败抛出异常
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) {
        log.info("登陆认证 -----------");
        JwtToken jwtToken = (JwtToken) authenticationToken;
        // 通过表单接收的用户名
        String token = (String) jwtToken.getPrincipal();
        if (StringUtils.isEmpty(token)) {
            throw new UnknownAccountException("token为空,请先登录");
        }
        String username = JwtUtils.getUsername(token);
        // 验证 token
        if (!JwtUtils.verify(token, username)) {
            throw new UnknownAccountException("token验证失败");
        }
        return new SimpleAuthenticationInfo(username, token, getName());
    }
}
